package com.yzg;

import lombok.extern.slf4j.Slf4j;

import java.util.LinkedList;

/**
 * @author misterWei
 * @create 2020年04月27号:22点37分
 * @mailbox forcontinue@163.com
 * 设计模式 - 生产者/消费者
 */
@Slf4j(topic = "c.QueueMode")
public class QueueMode {

    public static void main(String[] args) throws InterruptedException {
        Queue queue = new Queue(2);
        for (int i = 0; i < 3; i++) {
            new Thread(()->{
                Message pop = queue.pop();
                log.debug(pop.getMessage().toString());
            },"消息消费者 " + i).start();
        }

        for (int i = 0; i < 2; i++) {
            int temp = i;
            new Thread(()->{
                queue.putMessage(new Message(temp,"value = " + temp));
            },"消息生产者 "+i).start();
        }

    }
}

/**
 * 队列实例
 */
@Slf4j(topic = "c.Queue")
class Queue{
    private static final LinkedList<Message> queueLists = new LinkedList<>();
    private int limit;

    public Queue(int limit) {
        this.limit = limit;
    }

    //消息消费
    public Message pop(){
        synchronized (queueLists){
            while (queueLists.isEmpty()){
                try {
                    log.debug("队列正在阻塞,取不到消息");
                    queueLists.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            //拿到消息,唤醒生产方,看是否有消息阻塞
            Message message = queueLists.removeFirst();
            queueLists.notifyAll();
            return message;
        }


    }

    //消息生产
    public void putMessage(Message message){
        synchronized (queueLists){
            while (queueLists.size() >= limit){
                try {
                    log.debug("队列正在阻塞,队列已满");
                    queueLists.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            //存储list,唤醒消息消费方
            queueLists.addLast(message);
            queueLists.notifyAll();
        }

    }
}

/**
 * 消息实例
 */
class Message{
    private int id;
    private Object message;

    public Message(int id, Object message) {
        this.id = id;
        this.message = message;
    }

    public int getId() {
        return id;
    }

    public Object getMessage() {
        return message;
    }
}